package com.room.search.service;

import cn.afterturn.easypoi.csv.CsvImportUtil;
import cn.afterturn.easypoi.csv.entity.CsvImportParams;
import com.room.search.constant.HttpStatus;
import com.room.search.core.page.TableDataInfo;
import com.room.search.domain.CityList;
import com.room.search.domain.RoomSecondCityList;
import com.room.search.repository.CityListRepository;
import com.room.search.repository.RoomSecondCityListRepository;
import com.room.search.response.CityResponse;
import com.room.search.response.RoomResult;
import com.room.search.service.dto.city.*;

import java.io.IOException;
import java.net.URI;
import java.util.*;
import java.util.stream.Collectors;

import com.room.search.service.mapper.RoomSecondCityListMapper;
import com.room.search.util.PageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;

/**
 * Service Implementation for managing {@link CityList}.
 */
@Service
@Transactional
public class CityListService {

    private final Logger log = LoggerFactory.getLogger(CityListService.class);

    private final CityListRepository cityListRepository;
    private final RoomSecondCityListRepository secondCityListRepository;
    private final RoomSecondCityListMapper roomSecondCityListMapper;

    private String hotCityUrl;

    @Autowired
    private RestTemplate restTemplate;

    @Value("${application.weather.key}")
    private String key;

    @Value("${application.weather.url}")
    public void setNowUrl(String url) {
        this.hotCityUrl = url + "/city/top";
    }

    public CityListService(CityListRepository cityListRepository,
                           RoomSecondCityListRepository secondCityListRepository,
                           RoomSecondCityListMapper roomSecondCityListMapper) {
        this.cityListRepository = cityListRepository;
        this.secondCityListRepository = secondCityListRepository;
        this.roomSecondCityListMapper = roomSecondCityListMapper;
    }

    /**
     * Get all the cityLists.
     *
     * @return the list of entities.
     */
    @Transactional(readOnly = true)
    @Cacheable(cacheNames = "searchCityList")
    public CityConvertDTO findInitial() {
        log.debug("Request to get all CityLists");
        List<SearchCityListDTO> allDistinctByAdm1NameEn = cityListRepository.findAllDistinctByAdm1NameEn();
        Set<String> initial = new HashSet<>();
        Set<String> adm1Name;
        CityConvertDTO cityConvertDTO = new CityConvertDTO();
        Map<String, Set<String>> initialAndAdm1NameMap = new HashMap<>();
        allDistinctByAdm1NameEn.forEach(item-> initial.add(item.getCityInitial()));
        for (String s : initial) {
            adm1Name = new HashSet<>();
            for (SearchCityListDTO searchCityListDTO : allDistinctByAdm1NameEn) {
                if (s.equals(searchCityListDTO.getCityInitial())) {
                    adm1Name.add(searchCityListDTO.getAdm1Name());
                }
            }
            initialAndAdm1NameMap.put(s, adm1Name);
        }
        cityConvertDTO.setInitialMap(initialAndAdm1NameMap);
        return cityConvertDTO;
    }


    /**
     * 上传更新城市列表
     * @param file 城市文件
     */
    public void upload(MultipartFile file) throws IOException {
        CsvImportParams importParams = new CsvImportParams();
        importParams.setTitleRows(1);
        List<CityList> cityLists = CsvImportUtil.importCsv(file.getInputStream(), CityList.class, importParams);
        cityLists.forEach(item -> item.setCityInitial(item.getAdm1NameEN().substring(0, 1)));
        List<CityList> collect = cityLists.stream().distinct().collect(Collectors.toList());
        cityListRepository.deleteAll();
        cityListRepository.saveAll(collect);
    }

    /**
     * 查询热门城市接口
     */
    @Cacheable(cacheNames = "hotCity")
    public List<HotCityDTO> getHotCities() {
        MultiValueMap<String, String> uriVariables = new LinkedMultiValueMap<>(1);
        uriVariables.add("key", key);
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(hotCityUrl);
        URI uri = builder.queryParams(uriVariables).build().encode().toUri();
        CityResponse hotCityResponse = restTemplate.getForObject(uri, CityResponse.class);
        if (hotCityResponse == null) {
            return Collections.emptyList();
        }
        log.debug("response is {}", hotCityResponse);
        return hotCityResponse.getHotCityDTOS();
    }

    /**
     * 查询所有城市
     */
    public List<SearchCityListDTO> findAll() {
        return getSearchCityListDTOS();
    }

    @Cacheable(cacheNames = "all_cities")
    public List<SearchCityListDTO> getSearchCityListDTOS() {
        List<SearchCityListDTO> searchCityListDTOS = cityListRepository.findAllDistinctByAdm1NameEn();
        List<RoomSecondCityList> secondCityListRepositoryAll = secondCityListRepository.findAll();
        List<RoomSecondCityListDTO> roomSecondCityListDTOS = roomSecondCityListMapper.toDto(secondCityListRepositoryAll);
        searchCityListDTOS.forEach(searchCityListDTO -> {
            searchCityListDTO.setId(searchCityListDTO.getId()+33333);
            List<RoomSecondCityListDTO> roomSecondCityListDTOList = new ArrayList<>();
            roomSecondCityListDTOS.forEach(roomSecondCityListDTO -> {
                if (searchCityListDTO.getAdm2Name().equals(roomSecondCityListDTO.getAdm2NameZh())) {
                    roomSecondCityListDTOList.add(roomSecondCityListDTO);
                }
            });
            searchCityListDTO.setSecondCityListDTOS(roomSecondCityListDTOList);
        });
        return searchCityListDTOS;
    }

    /**
     * 根据省份去查询城市
     */
    @CachePut(cacheNames = "citiesByProvince")
    public List<SearchCityListDTO> findByProvince(String province) {
        return cityListRepository.findAllByAdm1Name(province);
    }

    /**
     * 管理后台获取的所有城市
     */
    public TableDataInfo getAdminAllCities(QueryCityDTO dto) {
        Pageable pageable = PageUtils.startPage();
        List<SearchCityListDTO> searchCityListDTOS = getSearchCityListDTOS();
        Page<SearchCityListDTO> page = PageUtils.listConvertToPage1(searchCityListDTOS, pageable);
        TableDataInfo dataInfo = new TableDataInfo();
        dataInfo.setCode(HttpStatus.SUCCESS);
        dataInfo.setMsg("查询成功");
        dataInfo.setRows(page.getContent());
        dataInfo.setTotal(page.getTotalElements());
        return dataInfo;
    }

    /**
     */
    public RoomResult updateSecond() {

        List<CityList> all = cityListRepository.findAll();
        List<RoomSecondCityList> secondCityLists = secondCityListRepository.findAll();
        secondCityLists.forEach(el-> all.forEach(allCity->{
            if (el.getAdm2NameZh().equals(allCity.getAdm2Name())) {
                el.setCityList(allCity);
            }
        }));
        secondCityListRepository.saveAll(secondCityLists);
        return RoomResult.success();
    }


    public RoomResult getAllArea() {
        List<RoomSecondCityList> all = secondCityListRepository.findAll();
        List<RoomSecondCityListDTO> roomSecondCityListDTOList = roomSecondCityListMapper.toDto(all);
        return RoomResult.success(roomSecondCityListDTOList);
    }
}
